#include "hplcsparklinkautosamplerprotocol.h"
#include "hplcsparklinkautosamplersendpacket.h"
#include "hplcsparklinkautosamplerparsepacket.h"
#include "hplcsparklinkautosamplerprotocoldata.h"

#include "hplcsparklinkmakepacket.h"
#include "hplcsparklinkfindpacket.h"
#include "hplcsparklinkcheckpacket.h"

#include "modulehplcautosamplerdefine.h"
#include "modulehplcautosamplercmdid.h"

namespace hplc
{
namespace sparklink
{

HplcSparkLinkAutoSamplerProtocol::HplcSparkLinkAutoSamplerProtocol(AutoSamplerParam &param, QObject *parent)
    : HplcSparkLinkAutoSamplerProtocol (*new HplcSparkLinkAutoSamplerProtocolData(), param, parent)
{

}

HplcSparkLinkAutoSamplerProtocol::HplcSparkLinkAutoSamplerProtocol(HplcSparkLinkAutoSamplerProtocolData &data, AutoSamplerParam &param, QObject *parent)
    : BaseProtocol (data, parent)
    , m_param(&param)
{
    data.m_id = 61; // 61为自动进样器的编号

    HplcSparkLinkMakePacket *maker = new HplcSparkLinkMakePacket(data);
    HplcSparkLinkCheckPacket *checker = new HplcSparkLinkCheckPacket(data, this);

    data.m_maker = maker;
    data.m_checker = checker;

    HplcSparkLinkAutoSamplerParsePacket *parser = new HplcSparkLinkAutoSamplerParsePacket(data, param, this);
    connect(parser, &BaseParsePacket::parseCompleted, this, &BaseProtocol::parseCompleted);
    HplcSparkLinkAutoSamplerSendPacket *sender = new HplcSparkLinkAutoSamplerSendPacket (data, this);
    connect(sender, &BaseSendPacket::requestSend, this, &BaseProtocol::requestSend);

    data.m_parser = parser;
    data.m_sender = sender;
}

HplcSparkLinkAutoSamplerProtocol::~HplcSparkLinkAutoSamplerProtocol()
{
    HplcSparkLinkAutoSamplerProtocolData *d = static_cast<HplcSparkLinkAutoSamplerProtocolData*>(m_d);
    delete d->m_sender;
    delete d->m_parser;
    delete d->m_checker;
    delete d->m_maker;
}

bool HplcSparkLinkAutoSamplerProtocol::setProtocolCmd(int id, QVariant &var)
{
    switch (id)
    {
        // analysisTime
        case hplc::sparklink::CmdID_P_AnalysisTime:
        {
            hplc::Time_t time = var.value<hplc::Time_t>();
            getSender()->P_analysisTime(time.hour, time.minute, time.second);
        }
        break;
        case hplc::sparklink::CmdID_SP_AnalysisTime:
        {
            getSender()->SP_analysisTime();
        }
        break;
        case hplc::sparklink::CmdID_SA_AnalysisTime:
        {
            getSender()->SA_analysisTime();
        }
        break;

        // loopVolume
        case hplc::sparklink::CmdID_P_LoopVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_loopVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_LoopVolume:
        {
            getSender()->SP_loopVolume();
        }
        break;

        // firstSamplePosition
        case hplc::sparklink::CmdID_P_FirstSamplePosition:
        {
            hplc::SamplePosition_t position = var.value<hplc::SamplePosition_t>();
            getSender()->P_firstSamplePosition(position.plateNumber, position.columnRowNumber.columnNumber, position.columnRowNumber.rowNumber);
        }
        break;
        case hplc::sparklink::CmdID_SP_FirstSamplePosition:
        {
            getSender()->SP_firstSamplePosition();
        }
        break;

        // lastSamplePosition
        case hplc::sparklink::CmdID_P_LastSamplePosition:
        {
            hplc::SamplePosition_t position = var.value<hplc::SamplePosition_t>();
            getSender()->P_lastSamplePosition(position.plateNumber, position.columnRowNumber.columnNumber, position.columnRowNumber.rowNumber);
        }
        break;
        case hplc::sparklink::CmdID_SP_LastSamplePosition:
        {
            getSender()->SP_lastSamplePosition();
        }
        break;

        // flushVolume
        case hplc::sparklink::CmdID_P_FlushVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_flushVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_FlushVolume:
        {
            getSender()->SP_flushVolume();
        }
        break;

        // numberOfInjectionsOrSample
        case hplc::sparklink::CmdID_P_NumberOfInjectionsOrSample:
        {
            quint8 number = var.toUInt();
            getSender()->P_numberOfInjectionsOrSample(number);
        }
        break;
        case hplc::sparklink::CmdID_SP_NumberOfInjectionsOrSample:
        {
            getSender()->SP_numberOfInjectionsOrSample();
        }
        break;
        case hplc::sparklink::CmdID_SA_NumberOfInjectionsOrSample:
        {
            getSender()->SA_numberOfInjectionsOrSample();
        }
        break;

        // injectionMode
        case hplc::sparklink::CmdID_P_InjectionMode:
        {
            quint8 mode = var.toUInt();
            getSender()->P_injectionMode(mode);
        }
        break;
        case hplc::sparklink::CmdID_SP_InjectionMode:
        {
            getSender()->SP_injectionMode();
        }
        break;

        // syringeVolume
        case hplc::sparklink::CmdID_P_SyringeVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_syringeVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_SyringeVolume:
        {
            getSender()->SP_syringeVolume();
        }
        break;

        // tubingVolume
        case hplc::sparklink::CmdID_P_TubingVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_tubingVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_TubingVolume:
        {
            getSender()->SP_tubingVolume();
        }
        break;

        // firstTransportVial
        case hplc::sparklink::CmdID_P_FirstTransportVial:
        {
            hplc::SamplePosition_t position = var.value<hplc::SamplePosition_t>();
            getSender()->P_firstTransportVial(position.plateNumber, position.vialNumber);
        }
        break;
        case hplc::sparklink::CmdID_SP_FirstTransportVial:
        {
            getSender()->SP_firstTransportVial();
        }
        break;

        // lastTransportVial
        case hplc::sparklink::CmdID_P_LastTransportVial:
        {
            hplc::SamplePosition_t position = var.value<hplc::SamplePosition_t>();
            getSender()->P_lastTransportVial(position.plateNumber, position.vialNumber);
        }
        break;
        case hplc::sparklink::CmdID_SP_LastTransportVial:
        {
            getSender()->SP_lastTransportVial();
        }
        break;

        // sampleNeedleHeight
        case hplc::sparklink::CmdID_P_SampleNeedleHeight:
        {
            quint8 level = var.toUInt();
            getSender()->P_sampleNeedleHeight(level);
        }
        break;
        case hplc::sparklink::CmdID_SP_SampleNeedleHeight:
        {
            getSender()->SP_sampleNeedleHeight();
        }
        break;

        // syringeSpeed
        case hplc::sparklink::CmdID_P_SyringeSpeed:
        {
            quint8 level = var.toUInt();
            getSender()->P_syringeSpeed(level);
        }
        break;
        case hplc::sparklink::CmdID_SP_SyringeSpeed:
        {
            getSender()->SP_syringeSpeed();
        }
        break;

        // syringeScaleFactor
        case hplc::sparklink::CmdID_P_SyringeSpeedScaleFactor:
        {
            quint8 factor = var.toUInt();
            getSender()->P_syringeSpeedScaleFactor(factor);
        }
        break;
        case hplc::sparklink::CmdID_SP_SyringeSpeedScaleFactor:
        {
            getSender()->SP_syringeSpeedScaleFactor();
        }
        break;

        // bufferVolume
        case hplc::sparklink::CmdID_P_BufferVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_bufferVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_BufferVolume:
        {
            getSender()->SP_bufferVolume();
        }
        break;

        // actualSampleNumber
        case hplc::sparklink::CmdID_SA_ActualSampleNumber:
        {
            getSender()->SA_actualSampleNumber();
        }
        break;

        // status
        case hplc::sparklink::CmdID_SA_Status:
        {
            getSender()->SA_status();
        }
        break;

        // errorCode
        case hplc::sparklink::CmdID_SA_ErrorCode:
        {
            getSender()->SA_errorCode();
        }
        break;

        // resetErrorCode
        case hplc::sparklink::CmdID_C_ResetErrorCode:
        {
            quint8 flag = var.toUInt();
            getSender()->C_resetErrorCode(flag);
        }
        break;

        // airSegment
        case hplc::sparklink::CmdID_P_AirSegment:
        {
            quint8 isUsed = var.toUInt();
            getSender()->P_airSegment(isUsed);
        }
        break;
        case hplc::sparklink::CmdID_SP_AirSegment:
        {
            getSender()->SP_airSegment();
        }
        break;

        // skipMissingSamplePosition
        case hplc::sparklink::CmdID_P_SkipMissingSamplePosition:
        {
            quint8 flag = var.toUInt();
            getSender()->P_skipMissingSamplePosition(flag);
        }
        break;
        case hplc::sparklink::CmdID_SP_SkipMissingSamplePosition:
        {
            getSender()->SP_skipMissingSamplePosition();
        }
        break;

        // headSpacePressure
        case hplc::sparklink::CmdID_P_HeadSpacePressure:
        {
            quint8 flag = var.toUInt();
            getSender()->P_headSpacePressure(flag);
        }
        break;
        case hplc::sparklink::CmdID_SP_HeadSpacePressure:
        {
            getSender()->SP_headSpacePressure();
        }
        break;

        // resetOutputAfterSerials
        case hplc::sparklink::CmdID_P_ResetOutputAfterSerials:
        {
            quint8 flag = var.toUInt();
            getSender()->P_resetOutputAfterSerials(flag);
        }
        break;
        case hplc::sparklink::CmdID_SP_ResetOutputAfterSerials:
        {
            getSender()->SP_resetOutputAfterSerials();
        }
        break;

        // usePrepMode
        case hplc::sparklink::CmdID_P_UsePrepMode:
        {
            quint8 flag = var.toUInt();
            getSender()->P_usePrepMode(flag);
        }
        break;
        case hplc::sparklink::CmdID_SP_UsePrepMode:
        {
            getSender()->SP_usePrepMode();
        }
        break;

        // traySegmentSettings
        case hplc::sparklink::CmdID_P_TraySegmentSettings:
        {
            hplc::TraySegmentSetting_t setting = var.value<hplc::TraySegmentSetting_t>();

            if (setting.leftTrayType == 3 && setting.rightTrayType == 3)
            {
                getSender()->P_traySegmentSettings_SinglePlate(setting.singlePlateType);
            }
            else
            {
                getSender()->P_traySegmentSettings(setting.leftTrayType,
                                                               setting.rightTrayType,
                                                               setting.separatePlateType.leftType,
                                                               setting.separatePlateType.rightType);
            }
        }
        break;
        case hplc::sparklink::CmdID_SP_TraySegmentSettings:
        {
            getSender()->SP_traySegmentSettings();
        }
        break;

        // syncCondition
        case hplc::sparklink::CmdID_P_SyncCondition:
        {
            hplc::SyncCondition_t condition = var.value<hplc::SyncCondition_t>();
            getSender()->P_syncCondition(condition.isSyncWithNextInjection,
                                                     condition.isSyncWithLoad,
                                                     condition.isSyncWithInject,
                                                     condition.isSyncWithValveWash);
        }
        break;
        case hplc::sparklink::CmdID_SP_SyncCondition:
        {
            getSender()->SP_syncCondition();
        }
        break;

        // injectionVolume
        case hplc::sparklink::CmdID_P_InjectionVolume:
        {
            quint16 volume = var.toUInt();
            getSender()->P_injectionVolume(volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_InjectionVolume:
        {
            getSender()->SP_injectionVolume();
        }
        break;

        // washBetween
        case hplc::sparklink::CmdID_P_WashBetween:
        {
            quint8 between = var.toUInt();
            getSender()->P_washBetween(between);
        }
        break;
        case hplc::sparklink::CmdID_SP_WashBetween:
        {
            getSender()->SP_washBetween();
        }
        break;

        // washTimes
        case hplc::sparklink::CmdID_P_WashTimes:
        {
            hplc::WashTimesEx_t times = var.value<hplc::WashTimesEx_t>();
            getSender()->P_washTimes(times.steps, times.times);
        }
        break;
        case hplc::sparklink::CmdID_SP_WashTimes:
        {
            quint8 steps = var.toUInt();
            getSender()->SP_washTimes(steps);
        }
        break;

        // washSyringeValveSolventPort
        case hplc::sparklink::CmdID_P_WashSyringeValveSolventPort:
        {
            hplc::WashSyringeValveSolventPortEx_t port = var.value<hplc::WashSyringeValveSolventPortEx_t>();
            getSender()->P_washSyringeValveSolventPort(port.steps, port.port);
        }
        break;
        case hplc::sparklink::CmdID_SP_WashSyringeValveSolventPort:
        {
            quint8 steps = var.toUInt();
            getSender()->SP_washSyringeValveSolventPort(steps);
        }
        break;

        // fillTransportPositionTimes
        case hplc::sparklink::CmdID_P_FillTransportPositionTimes:
        {
            hplc::FillTransportPositionTimes_t times = var.value<hplc::FillTransportPositionTimes_t>();
            getSender()->P_fillTransportPositionTimes(times.port, times.port);
        }
        break;
        case hplc::sparklink::CmdID_SP_FillTransportPositionTimes:
        {
            getSender()->SP_fillTransportPositionTimes();
        }
        break;

        // washVolume
        case hplc::sparklink::CmdID_P_WashVolume:
        {
            hplc::WashVolumeEx_t volume = var.value<hplc::WashVolumeEx_t>();
            getSender()->P_washVolume(volume.steps, volume.volume);
        }
        break;
        case hplc::sparklink::CmdID_SP_WashVolume:
        {
            quint8 steps = var.toUInt();
            getSender()->SP_washVolume(steps);
        }
        break;

        // useInMethod
        case hplc::sparklink::CmdID_P_UseInMethod:
        {
            hplc::UseInMethod_t isUseInMethod = var.value<hplc::UseInMethod_t>();
            getSender()->P_useInMethod(isUseInMethod.isUseTimedEvents,
                                                   isUseInMethod.isUseMix);
        }
        break;
        case hplc::sparklink::CmdID_SP_UseInMethod:
        {
            getSender()->SP_useInMethod();
        }
        break;

        // serialNumber
        case hplc::sparklink::CmdID_P_SerialNumber:
        {
            quint32 serial = var.toUInt();
            getSender()->P_serialNumber(serial);
        }
        break;
        case hplc::sparklink::CmdID_SP_SerialNumber:
        {
            getSender()->SP_serialNumber();
        }
        break;

        // clearMixOrUserProg
        case hplc::sparklink::CmdID_P_ClearMixOrUserProg:
        {
            quint8 flag = var.toUInt();
            getSender()->P_clearMixOrUserProg(flag);
        }
        break;

        // clearMethod
        case hplc::sparklink::CmdID_P_ClearMethod:
        {
            quint8 flag = var.toUInt();
            getSender()->P_clearMethod(flag);
        }
        break;

        // startOrStop
        case hplc::sparklink::CmdID_C_StartOrStop:
        {
            hplc::StartOrStopEx_t startOrStop = var.value<hplc::StartOrStopEx_t>();
            if (startOrStop.ai == 1)
            {
                getSender()->C_startOrStop_01(startOrStop.startUserProg,
                                                          startOrStop.startOrStop);
            }
            else
            {
                getSender()->C_startOrStop_02();
            }
        }
        break;

        // startOrStop
        case hplc::sparklink::CmdID_C_HoldOrContinue:
        {
            quint8 flag = var.toUInt();
            getSender()->C_holdOrContinue(flag);
        }
        break;

        // searchSamplePosition
        case hplc::sparklink::CmdID_C_SearchSamplePosition:
        {
            hplc::SearchSamplePosition_t position = var.value<hplc::SearchSamplePosition_t>();
            getSender()->C_searchSamplePosition(position.plateNumber,
                                                            position.platePosition);
        }
        break;

        // searchSamplePosition
        case hplc::sparklink::CmdID_C_InitialWash:
        {
            hplc::InitialWash_t initialWash = var.value<hplc::InitialWash_t>();
            getSender()->C_initialWash(initialWash.port,
                                                   initialWash.startInitialWash);
        }
        break;

        // moveSyringe
        case hplc::sparklink::CmdID_C_MoveSyringe:
        {
            quint8 moveSyringe = var.toUInt();
            getSender()->C_moveSyringe(moveSyringe);
        }
        break;

        // doorSensor
        case hplc::sparklink::CmdID_SA_DoorSensor:
        {
            getSender()->SA_doorSensor();
        }
        break;

        default:
        break;
    }
    return true;
}

bool HplcSparkLinkAutoSamplerProtocol::getProtocolCmd(int id, QVariant &var)
{
    return true;
}

HplcSparkLinkAutoSamplerSendPacket *HplcSparkLinkAutoSamplerProtocol::getSender()
{
    return static_cast<HplcSparkLinkAutoSamplerSendPacket*>(m_d->m_sender);
}

HplcSparkLinkAutoSamplerParsePacket *HplcSparkLinkAutoSamplerProtocol::getParser()
{
    return static_cast<HplcSparkLinkAutoSamplerParsePacket*>(m_d->m_parser);
}

ProtocolType HplcSparkLinkAutoSamplerProtocol::getProtocolType()
{
    return ProtocolType_SparkLink_AutoSampler;
}

void HplcSparkLinkAutoSamplerProtocol::onBaseTickTimeout()
{
    HplcSparkLinkProtocolCommonData *m_d = static_cast<HplcSparkLinkProtocolCommonData*>(this->m_d);
    m_d->m_checker->onBaseTickTimeout();
}

} // sparklink
} // hplc
